home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-13 / emac16ds.zip / REDISP.ASM < prev    next >
Assembly Source File  |  1991-05-18  |  43KB  |  1,816 lines

  1. ;History:514,1
  2. ;Sun May 13 23:33:05 1990 add a flag to enable/disable the scroll bar.
  3. ;Thu Apr 12 23:49:21 1990 store_firstline and store_lastline weren't really checking their parameters.
  4. ;Thu Feb 22 15:43:22 1990 output the blanks for a tab specially.
  5. ;Fri Feb 02 07:20:33 1990 don't forget the "more" symbol if we have trailing whitespace.
  6. ;Wed Nov 15 23:51:43 1989 use num_screen_cols-1 columns.
  7. ;Tue Nov 14 22:48:37 1989 add scrollbar code.
  8. ;Fri Jun 02 00:36:53 1989 gotoxy should position the cursor also.
  9. ;Sun Mar 26 20:45:02 1989 optimize a little code in store_current_window.
  10. ;06-26-88 23:53:50 in chrout, CR was changing the line w/o setting TRASHED.
  11. ;05-17-88 22:39:59 Make CGA scroll if only one line [kdb]
  12. ;05-17-88 22:09:22 Force redraw for CGA [kdb]
  13. ;05-17-88 19:39:15 Remove reference to scrwait [kdb]
  14. ;04-01-88 22:42:23 add tab_size to allow for varying tab sizes.
  15. ;03-26-88 14:37:44 on 40 column screens, fix horizontal scrolling (40 / 2) % 8 != 0
  16. ;11-16-87 23:18:13 remove memsize
  17. ;11-15-87 22:50:18 make w1_windseg, and w2_windseg for buffers.asm's sake.
  18. ;09-09-87 00:48:00 compute the middle of the screen, rather than assuming column 40.
  19. ;07-13-87 23:08:49 remove xyputch
  20. ;07-13-87 22:58:51 move the call to paint_screen into init_screen.
  21. ;07-07-87 22:37:35 also check for eof in trailing blanks code
  22. ;07-07-87 22:12:44 check for bottom correctly in redraw_line
  23. ;07-07-87 22:10:54 in redraw_line, move the check where we need it.
  24. ;07-06-87 06:52:39 use botbot to check for eof, not LINENEW
  25.     .xlist
  26.  
  27. HT    equ    09h
  28. LF    equ    0ah
  29. CR    equ    0dh
  30. LINENEW    equ    CR+LF*256    ;the way a newline is stored in memory.
  31.  
  32. TRAIL_BLANK    equ    4dh
  33. TRAIL_TAB    equ    4eh
  34. MORE_CHAR    equ    52h
  35. NEWLINE_CHAR    equ    54h
  36. UP_CHAR        equ    55h
  37. DOWN_CHAR    equ    56h
  38. TAB_BLANK    equ    57h
  39.  
  40. bufseg    segment    byte public
  41.  
  42.     extrn    toptop: word
  43.     extrn    topbot: word
  44.     extrn    bottop: word
  45.     extrn    botbot: word
  46.  
  47.     extrn    linecount: word
  48.     extrn    linesbefore: word
  49.  
  50. bufseg    ends
  51.  
  52. data    segment    byte public
  53.  
  54.   if 1
  55.     public    w1, w2, this_point, this_row, other_row, topbotpercent
  56.     public    botpercent, toppercent, firstlimit, lastlimit, overwrite_row
  57.     public    overwrite_col, screen_column, window, inversed, inverse_mark
  58.     public    showblanks
  59.   endif
  60.  
  61. ;pointrow contains the row that the cursor is currently on, relative to the
  62. ;  screen boundaries.  Pointrow may be negative if the point is above the screen,
  63. ;  or it may be larger than max_screen_line if the point is below the screen.
  64.  
  65. wind_struc    struc
  66. windseg        dw    ?
  67. pointrow    dw    ?
  68. firstline    db    ?
  69. lastline    db    ?
  70. firstpossible    db    ?
  71. lastpossible    db    ?
  72. firstcolumn    dw    ?
  73. wind_struc    ends
  74.  
  75. w1    wind_struc<>
  76.  
  77. w2    wind_struc<>
  78.  
  79.     public    w1_windseg, w2_windseg
  80. w1_windseg    equ    w1.windseg
  81. w2_windseg    equ    w2.windseg
  82.  
  83.  
  84. this_point    dw    ?        ;->point in the current file.
  85. this_row    dw    ?        ;row of point on screen.
  86. other_row    dw    ?        ;row of point in other window.
  87.  
  88. topbotpercent    label    word
  89. botpercent    db    ?
  90. toppercent    db    ?
  91.  
  92. firstlastlimits    label    word
  93. firstlimit    db    ?
  94. lastlimit    db    ?
  95.  
  96.  
  97.     public    tab_size
  98. tab_size    dw    7        ;mask for tab stops.
  99.  
  100.     public    next_redisp_line
  101. next_redisp_line    dw    0
  102.  
  103.     public    overwrite_flag
  104. overwrite_flag    db    0        ;=0 if not overwriting.
  105.  
  106. overwrite_rowcol    label    word
  107. overwrite_row    db    0
  108. overwrite_col    db    0
  109.  
  110. ;the following externs are in the computer-dependent file
  111.     extrn    max_screen_line: byte
  112.     extrn    num_screen_cols: byte
  113.  
  114. ;the following externs are in 'buffers'
  115.     extrn    textseg: word
  116.  
  117. screen_column    dw    ?
  118.  
  119. ;window contains a list of which lines should be moved where, and which
  120. ;  lines need to be redrawn.  If an entry is positive, then the line which is
  121. ;  currently at x belongs at window[x].  If an entry is TRASHED, it
  122. ;  should be redrawn.
  123. ;inversed contains a list of which lines currently show inverse video.
  124. window        db    128 dup(?)    ;128 is > max_screen_line
  125. inversed    db    128 dup(?)    ;. .
  126. inverse_flag    db    0        ;=0 means no inversing.
  127.     public    inverse_seg        ;used by buffers.asm to adjust.
  128. inverse_seg    dw    0        ;segment of marked buffer.
  129.     public    inversing        ;used by ibm.asm or z100.asm to control
  130. inversing    dw    0        ;  which lines are inversed.
  131.  
  132. inverse_mark    dw    ?        ;pointing to the inverse mark.
  133.  
  134. TRASHED        equ    -1        ;note that TRASHED must be negative.
  135.  
  136. showblanks    db    0
  137.  
  138. data    ends
  139.  
  140. b_struc    struc
  141. b    db    ?
  142. b_struc    ends
  143.  
  144. w_struc    struc
  145. w    dw    ?
  146. w_struc    ends
  147.  
  148. byte_ptr    label    byte
  149.  
  150. code    segment    byte public
  151. ;all the routines in this segment are entered with ds=data, es=data
  152.     assume    cs:code, ds:data, es:data
  153.  
  154.  
  155. ;the following externs are in the computer-dependent file.
  156.     extrn    move_line: near
  157.     extrn    clear_to_eol: near
  158.     extrn    xychrout: near
  159.     extrn    hardware_roll_up: near
  160.     extrn    hardware_roll_down: near
  161.     extrn    position_cursor: near
  162.     extrn    read_ibm_cga: near
  163.     extrn    read_scroll_bar: near
  164.  
  165. ;the following externs are in 'memory'
  166.     extrn    compute_cursor$: near
  167.     extrn    set_line$: near
  168.  
  169. ;the following externs are in 'buffers'
  170.     extrn    buffer_number: near
  171.         ;enter with bx=paragraph of buffer.
  172.         ;exit with ax=number of buffer.
  173.     extrn    buffer_allocate: near
  174.     extrn    find_buffer: near
  175.         ;enter with cx=buffer number.
  176.         ;exit with nc, dx set to that buffer if it exists, cy otherwise.
  177.  
  178. ;the following externs are in 'marks'
  179.     extrn    read_mark$: near
  180.     extrn    goto_mark$: near
  181.     extrn    get_split_mark: near
  182.     extrn    get_mark: near
  183.     extrn    split_at_point: near
  184.     extrn    set_mark_si: near
  185.     extrn    set_mark: near
  186.     extrn    stack_marks: near
  187.     extrn    goto_mark: near
  188.  
  189.  
  190.     public    read_current_window
  191. read_current_window:
  192.     mov    ax,1            ;probably window 1.
  193.     cmp    w2.windseg,0        ;no window 2 - must be 1.
  194.     je    read_current_window_1
  195.     mov    bl,w1.firstline
  196.     cmp    bl,w2.firstline
  197.     jb    read_current_window_1
  198.     inc    ax
  199. read_current_window_1:
  200.     ret
  201.  
  202.  
  203.     public    store_current_window
  204. store_current_window:
  205.     cmp    ax,1
  206.     jne    store_current_window_1
  207.     mov    al,w1.firstline
  208.     cmp    al,w2.firstline
  209.     jb    store_current_window_2
  210.     jmp    short store_current_window_3
  211. store_current_window_1:
  212.     cmp    ax,2
  213.     jne    store_current_window_2
  214.     mov    al,w1.firstline
  215.     cmp    al,w2.firstline
  216.     ja    store_current_window_2
  217. store_current_window_3:
  218.     cmp    w2.windseg,0        ;is there a second window?
  219.     je    store_current_window_2    ;no - don't swap.
  220.     call    swap_other_row
  221.     call    swap_windows
  222. store_current_window_2:
  223.     ret
  224.  
  225.  
  226. swap_other_row:
  227.     mov    ax,w1.windseg        ;are we in the other window?
  228.     cmp    ax,w2.windseg
  229.     jne    swap_other_row_1    ;no - no worries.
  230.     push    w1.pointrow        ;remember what other_row will be.
  231.  
  232.     mov    ax,1
  233.     call    stack_marks
  234.     mov    ax,'*'*256+'0'        ;0 := *
  235.     call    set_mark
  236.     mov    ax,'.'*256+'*'        ;* := .
  237.     call    set_mark
  238.     mov    al,'0'            ;. := 0
  239.     call    goto_mark
  240.     mov    ax,0
  241.     call    stack_marks
  242.  
  243.     pop    other_row
  244. swap_other_row_1:
  245.     ret
  246.  
  247.  
  248.     public    read_other_window
  249. read_other_window:
  250.     mov    bx,w2.windseg
  251.     or    bx,bx
  252.     je    read_other_window_1
  253.     call    buffer_number
  254.     ret
  255. read_other_window_1:
  256.     xor    ax,ax
  257.     ret
  258.  
  259.  
  260.     public    store_other_window
  261. store_other_window:
  262. ;enter with ax=buffer segment to show.
  263.     mov    cx,ax            ;do they want one window?
  264.     jcxz    store_other_window_3    ;yes.
  265.     call    find_buffer        ;find the buffer.
  266.     jc    store_other_window_3    ;can't find it - give them one window.
  267.  
  268.     cmp    w2.windseg,0        ;do we have another window to set?
  269.     jne    store_other_window_1    ;yes - just set it.
  270.     push    dx
  271.     call    split_screen
  272.     pop    dx
  273. store_other_window_1:
  274.     cmp    dx,w2.windseg        ;is it already showing?
  275.     je    store_other_window_2    ;yes - they're being silly.
  276.  
  277.     mov    w2.windseg,dx        ;show the buffer here.
  278.  
  279.     cmp    w1.windseg,dx        ;is this buffer also in w1?
  280.     jne    store_other_window_4    ;no - no worries.
  281.  
  282.     mov    ax,w1.pointrow        ;the place that the this window is at
  283.     mov    other_row,ax        ;  becomes the other row.
  284.  
  285.     mov    ax,'.'*256+'*'        ;set the split mark to the point.
  286.     call    set_mark
  287.  
  288. store_other_window_4:
  289.     mov    bl,w2.firstline        ;trash what's there.
  290.     mov    al,w2.lastline
  291.     call    trash_some_lines
  292. store_other_window_2:
  293.     ret
  294.  
  295. store_other_window_3:
  296.     mov    w2.windseg,0
  297.     mov    al,max_screen_line    ;fill the screen with this window.
  298.     mov    w1.lastline,al
  299.     mov    w1.firstline,0
  300.     mov    si,offset w1
  301.     call    set_window_percent
  302.     call    paint_screen
  303.     ret
  304.  
  305.  
  306. split_screen:
  307.     mov    al,max_screen_line
  308.     mov    w2.lastline,al
  309.     sar    al,1
  310.     dec    al
  311.     mov    w1.lastline,al
  312.     add    al,2
  313.     mov    w2.firstline,al
  314. split_recompute:
  315.     mov    si,offset w1
  316.     call    set_window_percent
  317.  
  318.     mov    si,offset w2
  319.     call    set_window_percent
  320.  
  321.     call    paint_screen
  322.  
  323.     ret
  324.  
  325.  
  326.     public    store_firstline
  327. store_firstline:
  328.     cmp    w2.windseg,0        ;do we really have two windows?
  329.     je    store_firstline_1    ;no.
  330.     cmp    w1.firstline,0        ;are we the top window?
  331.     je    store_firstline_1    ;yes - we can't set it.
  332.     cmp    al,2            ;less than 2?
  333.     jb    store_firstline_1    ;yes - would leave no room for the top.
  334.     cmp    al,max_screen_line    ;at the screen size?
  335.     ja    store_firstline_1    ;yes - would leave no room for us.
  336.     mov    w1.firstline,al
  337.     sub    al,2
  338.     mov    w2.lastline,al
  339.  
  340.     call    split_recompute
  341. store_firstline_1:
  342.     ret
  343.  
  344.  
  345.     public    store_lastline
  346. store_lastline:
  347.     cmp    w2.windseg,0        ;do we really have two windows?
  348.     je    store_lastline_1    ;no.
  349.     cmp    w1.firstline,0        ;are we the top window?
  350.     jne    store_lastline_1    ;no - we can't set it.
  351.     mov    ah,max_screen_line
  352.     sub    ah,2            ;leave room for the bottom window.
  353.     cmp    al,ah            ;at the screen size?
  354.     ja    store_lastline_1    ;yes - would leave no room for the bot.
  355.     mov    w1.lastline,al
  356.     add    al,2
  357.     mov    w2.firstline,al
  358.  
  359.     call    split_recompute
  360. store_lastline_1:
  361.     ret
  362.  
  363.  
  364.     public    store_showblanks
  365. store_showblanks:
  366.     cmp    showblanks,al        ;are we changing it?
  367.     mov    showblanks,al        ;store it in any case.
  368.     je    store_showblanks_1    ;if we changed it, paint the window.
  369.     call    paint_window
  370. store_showblanks_1:
  371.     ret
  372.  
  373.  
  374.     public    read_showblanks
  375. read_showblanks:
  376.     mov    al,showblanks
  377.     ret
  378.  
  379.  
  380.     public    read_firstline
  381. read_firstline:
  382.     mov    al,w1.firstline
  383.     ret
  384.  
  385.  
  386.     public    read_lastline
  387. read_lastline:
  388.     mov    al,w1.lastline
  389.     ret
  390.  
  391.  
  392.     public    read_newrow
  393. read_newrow:
  394.     mov    ax,w1.pointrow
  395.     ret
  396.  
  397.  
  398.     public    read_firstcolumn
  399. read_firstcolumn:
  400.     mov    ax,w1.firstcolumn
  401.     ret
  402.  
  403.  
  404.     public    store_firstcolumn
  405. store_firstcolumn:
  406.     and    ax,not 7        ;go to the next leftmost tab stop.
  407.     push    ax
  408.     mov    bl,w1.firstline
  409.     mov    al,w1.lastline
  410.     call    trash_some_lines
  411.     pop    w1.firstcolumn
  412.     ret
  413.  
  414.  
  415.     public    read_top_percent
  416. read_top_percent:
  417.     mov    al,toppercent
  418.     ret
  419.  
  420.  
  421.     public    read_bot_percent
  422. read_bot_percent:
  423.     mov    al,botpercent
  424.     ret
  425.  
  426.  
  427.     public    store_top_percent
  428. store_top_percent:
  429.     mov    toppercent,al
  430.     mov    si,offset w1
  431.     call    set_window_percent
  432.     ret
  433.  
  434.  
  435.     public    store_bot_percent
  436. store_bot_percent:
  437.     mov    botpercent,al
  438.     mov    si,offset w1
  439.     call    set_window_percent
  440.     ret
  441.  
  442.  
  443.     public    read_inverse_mark
  444. read_inverse_mark:
  445.     mov    al,inverse_flag
  446.     ret
  447.  
  448.  
  449.     public    store_inverse_mark
  450. store_inverse_mark:
  451.     mov    inverse_flag,al
  452.     mov    ax,textseg
  453.     mov    inverse_seg,ax
  454.     ret
  455.  
  456.     public    init_screen
  457. init_screen:
  458.     xor    al,al
  459.     mov    w1.firstline,al
  460.     mov    w1.firstpossible,al
  461.     mov    al,max_screen_line    ;fill the screen with this window.
  462.     mov    w1.lastline,al
  463.     mov    w1.lastpossible,al
  464.     mov    w1.firstcolumn,0
  465.     mov    ax,textseg
  466.     mov    w1.windseg,ax
  467.     call    paint_screen
  468.     ret
  469.  
  470.  
  471.     public    gotoxy
  472. gotoxy:
  473.     cmp    dl,max_screen_line    ;is max_screen_line ok?
  474.     jbe    gotoxy_1        ;yes.
  475.     mov    dl,max_screen_line    ;no - take min(dl, max_screen_line)
  476. gotoxy_1:
  477.     cmp    dh,num_screen_cols    ;are we on the screen?
  478.     jb    gotoxy_2
  479.     mov    dh,num_screen_cols    ;no - take min(dh, num_screen_cols-1)
  480.     dec    dh
  481. gotoxy_2:
  482.     mov    overwrite_rowcol,dx
  483.     call    position_cursor
  484.     ret
  485.  
  486.  
  487.     public    chrout
  488. chrout:
  489. ;enter with ax=char to "type" on screen.
  490. ;preserve si.
  491.     cmp    overwrite_flag,0    ;are we already overwriting?
  492.     jne    chrout_1        ;yes.
  493.     mov    overwrite_flag,1    ;say that we're overwriting
  494.     mov    window[0],TRASHED    ;trash the first line.
  495. chrout_1:
  496.     mov    dx,overwrite_rowcol    ;get the cursor position.
  497.     cmp    al,CR            ;go to left margin?
  498.     jne    chrout_4
  499.     mov    bh,0            ;trash the line because we're clearing it.
  500.     mov    bl,dl
  501.     mov    window[bx],TRASHED
  502.     call    clear_to_eol        ;yes - clear to end here.
  503.     mov    dh,0
  504.     jmp    chrout_exit
  505. chrout_4:
  506.     cmp    al,LF            ;go down a line?
  507.     jne    chrout_5
  508.     inc    dl
  509.     cmp    dl,max_screen_line    ;are we past the last line?
  510.     jbe    chrout_exit        ;no.
  511.     call    paint_screen        ;yes - paint the whole thing.
  512.     mov    ah,0            ;;KAN
  513.     mov    al,max_screen_line    ;;KAN
  514.     call    hardware_roll_up    ;yes - roll the screen up.
  515.     jnc    chrout_6
  516.     mov    dl,1            ;have to software scroll.
  517. chrout_7:
  518.     mov    al,dl
  519.     dec    al
  520.     call    move_line
  521.     inc    dl
  522.     cmp    dl,max_screen_line
  523.     jbe    chrout_7
  524. chrout_6:
  525.     mov    dl,max_screen_line    ;say on the last line.
  526.     push    dx            ;clear the entire line.
  527.     mov    dh,0
  528.     call    clear_to_eol
  529.     pop    dx
  530.     jmp    short chrout_exit
  531. chrout_5:
  532.     cmp    al,HT
  533.     jne    chrout_8
  534. chrout_9:
  535.     mov    ah,0
  536.     mov    al,' '
  537.     call    chrout_putch
  538.     test    dh,byte ptr tab_size
  539.     jnz    chrout_9
  540.     jmp    short chrout_exit
  541. chrout_8:
  542.     call    chrout_putch
  543. chrout_exit:
  544.     mov    overwrite_rowcol,dx    ;remember where we are.
  545.     call    position_cursor
  546.     ret
  547.  
  548.  
  549. chrout_putch:
  550.     mov    bh,0            ;trash the line.
  551.     mov    bl,dl
  552.     mov    window[bx],TRASHED
  553.     call    xychrout
  554.     inc    dh
  555.     ret
  556.  
  557.  
  558.     public    redisplay
  559. redisplay:
  560.  
  561.     mov    ax,textseg        ;is the current buffer showing in w1?
  562.     cmp    ax,w1.windseg
  563.     je    redisplay$_1        ;yes - all ok.
  564.  
  565.     xchg    w1.windseg,ax        ;no - put it in this window.
  566.     cmp    ax,w2.windseg        ;was the old w1 showing in w2?
  567.     jne    redisplay$_2        ;no - nothing special.
  568.  
  569.     push    ds
  570.     mov    ds,w2.windseg
  571.     mov    al,'*'            ;yes - make the split mark the point
  572.     call    goto_mark$
  573.     pop    ds
  574.  
  575. redisplay$_2:
  576.  
  577.     mov    bl,w1.firstline
  578.     mov    al,w1.lastline
  579.     call    trash_some_lines
  580.  
  581.     mov    ax,w1.windseg        ;is this buffer also in w2?
  582.     cmp    ax,w2.windseg
  583.     jne    redisplay$_1        ;no - no worries.
  584.  
  585.     mov    bl,w2.firstline        ;yes - trash one line so that
  586.     mov    bh,0            ;  the point is recomputed.  hack, hack.
  587.     mov    window[bx],TRASHED
  588.  
  589.     mov    ax,w2.pointrow        ;the place that the other window is at
  590.     mov    other_row,ax        ;  becomes the other row.
  591.  
  592.     mov    ax,'.'*256+'*'        ;set the split mark to the point.
  593.     call    set_mark
  594.  
  595. redisplay$_1:
  596.  
  597.     mov    overwrite_flag,0    ;no longer overwriting.
  598.     mov    dx,0            ;start in the upper left hand corner
  599.     mov    overwrite_rowcol,dx    ;  the next time we overwrite.
  600.   if 0
  601.     mov    dx,0*256+24        ;dh=column, dl=row.
  602.     mov    si,offset window
  603. rd_0:
  604.     lodsb
  605.     add    al,'A'
  606.     call    xychrout
  607.     inc    dh
  608.     cmp    dh,25
  609.     jb    rd_0
  610.     mov    si,offset inversed
  611. rd_1:
  612.     lodsb
  613.     add    al,'0'
  614.     call    xychrout
  615.     inc    dh
  616.     cmp    dh,48
  617.     jb    rd_1
  618.  
  619.   endif
  620.  
  621.     push    ds
  622.     mov    ds,w1.windseg
  623.     assume    ds:bufseg
  624.  
  625.     mov    si,topbot
  626.     mov    this_point,si
  627.  
  628.     mov    ax,next_redisp_line
  629.  
  630.     call    force_point_into_window
  631.     mov    ax,w1.pointrow
  632.     mov    this_row,ax
  633.  
  634.     call    redraw_trashed
  635.     call    write_scrollbar
  636.  
  637.     mov    ax,this_row
  638.     mov    w1.pointrow,ax
  639.  
  640.     pop    ds
  641.     assume    ds:data
  642.  
  643.     mov    dx,screen_column
  644.     sub    dx,w1.firstcolumn
  645.     mov    dh,dl
  646.     mov    dl,byte ptr w1.pointrow
  647.     call    position_cursor
  648.  
  649.     cmp    w2.windseg,0        ;is there a second window?
  650.     je    redisplay_one        ;no.
  651.     call    swap_windows
  652.     push    ds
  653.     mov    ax,w1.windseg        ;are they the same file?
  654.     cmp    ax,w2.windseg
  655.     mov    ds,ax            ;really w2.
  656.     assume    ds:bufseg
  657.     jne    redisplay__2
  658. ;two windows into the same buffer.
  659.     call    get_split_mark        ;get the split mark.
  660.     cmp    si,bottop        ;are we at the point?
  661.     jne    redisplay__1        ;no.
  662.     mov    si,topbot        ;yes - always use the top point.
  663. redisplay__1:
  664.     mov    this_point,si
  665.     mov    ax,other_row        ;get the row in the other window.
  666.     mov    this_row,ax
  667.     call    redraw_trashed
  668.     call    write_scrollbar
  669.     mov    ax,this_row
  670.     xchg    other_row,ax
  671.     sub    ax,other_row        ;how much did we adjust it by?
  672.     sub    w1.pointrow,ax        ;adjust pointrow, too.
  673.  
  674.     jmp    short redisplay__3
  675. redisplay__2:
  676. ;two windows, two buffers.
  677.     mov    si,topbot
  678.     mov    this_point,si
  679.     xor    ax,ax
  680.     call    force_point_into_window
  681.     mov    ax,w1.pointrow
  682.     mov    this_row,ax
  683.     call    redraw_trashed
  684.     call    write_scrollbar
  685.     mov    ax,this_row
  686.     mov    w1.pointrow,ax
  687. redisplay__3:
  688.     call    swap_windows
  689.     pop    ds
  690.     assume    ds:data
  691. redisplay_one:
  692.     mov    next_redisp_line,0    ;no more desired line
  693.     ret
  694.  
  695.  
  696. code    ends
  697.  
  698. code    segment    byte public
  699. ;all the code in this segment is entered with ds=bufseg, es=data
  700.     assume    cs:code, ds:bufseg, es:data
  701.  
  702.  
  703. write_scrollbar:
  704.     call    read_scroll_bar        ;should we write a scroll bar?
  705.     je    write_scrollbar_4
  706.     mov    ax,this_point
  707.     cmp    ax,topbot        ;is it in the lower half?
  708.     jbe    write_scrollbar_3    ;go if yes.
  709.     sub    ax,bottop        ;change this_point into a count of
  710.     add    ax,topbot        ;  characters before point.
  711. write_scrollbar_3:
  712.     sub    ax,toptop        ;now subtract off the beginning.
  713.     mov    dl,w1.lastline
  714.     sub    dl,w1.firstline
  715.     xor    dh,dh
  716.     mul    dx
  717.  
  718.     mov    cx,topbot
  719.     sub    cx,toptop
  720.     add    cx,botbot
  721.     sub    cx,bottop
  722.     inc    cx
  723.  
  724.     div    cx
  725.     add    al,w1.firstline
  726.     inc    al            ;remember, we aren't counting the first line.
  727.     mov    bl,al
  728.  
  729.     mov    dl,w1.firstline
  730.     mov    dh,num_screen_cols
  731.     mov    ax,8*256+UP_CHAR
  732.     call    xychrout
  733.  
  734.     inc    dl
  735. write_scrollbar_1:
  736.  
  737.     mov    ax,0b1h            ;50% halftone block
  738.     cmp    dl,bl            ;did we reach our cursor point yet?
  739.     jne    write_scrollbar_2
  740.     mov    ax,0dbh            ;solid block
  741. write_scrollbar_2:
  742.     call    xychrout
  743.  
  744.     inc    dl
  745.     cmp    dl,w1.lastline
  746.     jbe    write_scrollbar_1
  747.  
  748.     mov    ax,8*256+DOWN_CHAR
  749.     call    xychrout
  750. write_scrollbar_4:
  751.     ret
  752.  
  753.  
  754. set_window_percent:
  755. ;note that set_window_percent doesn't use ds.
  756. ;enter with si->window to set.
  757.     mov    cl,100
  758.     mov    ch,data:[si].lastline
  759.     sub    ch,data:[si].firstline
  760.     inc    ch
  761.     mov    al,toppercent
  762.     mul    ch
  763.     div    cl
  764.     cmp    al,ch
  765.     jb    set_window_percent_1
  766.     xor    al,al
  767. set_window_percent_1:
  768.     add    al,data:[si].firstline
  769.     mov    data:[si].firstpossible,al
  770.     mov    al,botpercent
  771.     mul    ch
  772.     div    cl
  773.     mov    ch,data:[si].lastline
  774.     sub    ch,al
  775.     jae    set_window_percent_2
  776.     mov    ch,data:[si].lastline
  777. set_window_percent_2:
  778.     mov    data:[si].lastpossible,ch
  779.     ret
  780.  
  781.  
  782. roll_window_down_2_j_1:
  783.     jmp    roll_window_down_2
  784. roll_window_down_5_j_1:
  785.     jmp    roll_window_down_5
  786.  
  787. roll_window_down:
  788. ;roll the window down until pointrow is in the window.
  789.  
  790.     mov    al,firstlimit
  791.     cbw
  792.     cmp    w1.pointrow,ax        ;if pointrow>=firstlimit, we don't
  793.     jge    roll_window_down_2_j_1    ;  need to roll down.
  794.  
  795. ;Are there any lines now on the screen that will remain?  Go if not.
  796.  
  797.     mov    cx,w1.pointrow
  798.     mov    bh,0
  799.     mov    bl,w1.lastline
  800.     add    cx,bx
  801.     mov    bl,w1.firstline
  802.     sub    cx,bx
  803.     mov    bl,firstlimit
  804.     cmp    cx,bx
  805.     jl    roll_window_down_5_j_1    ;we have to repaint the entire window.
  806.  
  807. ;Repaint screen if CGA, believe it or not, it is faster
  808.     call    read_ibm_cga
  809.     cmp    al,0
  810.     je    roll_window_down_normal
  811.     mov    cx,w1.pointrow
  812.     mov    bl,firstlimit
  813.     mov    bh,0
  814.     sub    cx,bx
  815.     inc    cx            ;Scroll if only one line
  816.     jnz    roll_window_down_5_j_1    ; it looks better
  817.  
  818. roll_window_down_normal:
  819.  
  820.     mov    dx,w1.pointrow
  821.     mov    cl,w1.firstline
  822.     mov    ch,0
  823.     sub    dx,cx
  824.     inc    dx
  825.  
  826. ;now compute the number of times we need to roll.
  827.  
  828.     mov    cx,w1.pointrow
  829.     sub    cx,bx
  830.     mov    w1.pointrow,bx        ;bx is firstlimit
  831.     neg    cx
  832.  
  833.   if 0
  834. ;Can we use the hardware scroll?  Go if not.
  835.  
  836.     cmp    w1.firstline,0
  837.     jne    roll_window_down_3
  838.     mov    al,max_screen_line
  839.     cmp    w1.lastline,al
  840.     jne    roll_window_down_3
  841.   endif
  842.  
  843. ;Use the hardware scroll unless there isn't one.
  844.  
  845.     xchg    cx,dx            ;get the distance to skip
  846.     call    skip_to_line
  847.     mov    cx,dx
  848.  
  849. roll_window_down_4:
  850.     mov    ah,w1.firstline
  851.     mov    al,w1.lastline
  852.     call    hardware_roll_down
  853.     jc    roll_window_down_3    ;can't hardware roll.
  854.  
  855. ;now adjust window[] for the change we just made to the screen.
  856.  
  857.     mov    bl,w1.firstline
  858.     mov    bh,0
  859.     mov    al,window[bx]        ;save the current values for later.
  860.     mov    ah,inversed[bx]
  861.     push    ax
  862.     push    si
  863.     call    redraw_compare        ;remember if we're inversing here.
  864.     mov    inversed[bx],al
  865.     call    redraw_line
  866.     call    remember_redrawn
  867.     pop    si
  868.     call    prevline
  869.     mov    window[bx],bl        ;remember that this line is real.
  870.     pop    ax            ;restore the old values.
  871. roll_window_down_6:
  872.     cmp    al,TRASHED        ;is this a trashed line?
  873.     je    roll_window_down_7
  874.     inc    al            ;no - say that the line's moved up.
  875.     cmp    al,max_screen_line    ;did it roll off the screen?
  876.     jbe    roll_window_down_7    ;no.
  877.     mov    al,TRASHED        ;yes - it's gone.
  878. roll_window_down_7:
  879.     inc    bl
  880.     xchg    al,window[bx]
  881.     xchg    ah,inversed[bx]
  882.     cmp    bl,w1.lastline
  883.     jb    roll_window_down_6
  884.     loop    roll_window_down_4
  885.     jmp    short roll_window_down_2
  886.  
  887. ;repaint screen.
  888.  
  889. roll_window_down_5:
  890.     call    center_this
  891.     jmp    short roll_window_down_2
  892.  
  893. ;Use software scroll.  All we do is roll the window array.
  894.  
  895. roll_window_down_3:
  896.     mov    bl,w1.firstline
  897.     mov    bh,0
  898.     mov    al,window[bx]        ;save the current value for later.
  899.     mov    ah,inversed[bx]
  900.     mov    window[bx],TRASHED
  901. roll_window_down_1:
  902.     inc    bl
  903.     xchg    al,window[bx]
  904.     xchg    ah,inversed[bx]
  905.     cmp    bl,w1.lastline
  906.     jb    roll_window_down_1
  907.     loop    roll_window_down_3
  908. roll_window_down_2:
  909.     ret
  910.  
  911.  
  912. roll_window_up_2_j_1:
  913.     jmp    roll_window_up_2
  914. roll_window_up_5_j_1:
  915.     jmp    roll_window_up_5
  916.  
  917. roll_window_up:
  918.  
  919.     mov    al,lastlimit
  920.     cbw
  921.     cmp    w1.pointrow,ax        ;if pointrow<=lastlimit, we don't
  922.     jle    roll_window_up_2_j_1    ;  need to roll up.
  923.  
  924. ;compute: pointrow-(lastline-firstline) > lastlimit
  925.  
  926. ;Are there any lines now on the screen that will remain?  Go if not.
  927.  
  928.     mov    cx,w1.pointrow
  929.     mov    bh,0
  930.     mov    bl,w1.firstline
  931.     add    cx,bx
  932.     mov    bl,w1.lastline
  933.     sub    cx,bx
  934.     mov    bl,lastlimit
  935.     cmp    cx,bx
  936.     jg    roll_window_up_5_j_1    ;we have to repaint the entire window.
  937.  
  938. ;Repaint screen if CGA, believe it or not, it is faster
  939.     call    read_ibm_cga
  940.     cmp    al,0
  941.     je    roll_window_up_normal
  942.     mov    cx,w1.pointrow
  943.     mov    bl,lastlimit
  944.     mov    bh,0
  945.     sub    cx,bx
  946.     dec    cx            ;Scroll if only one line
  947.     jnz    roll_window_up_5_j_1    ; it looks better
  948.  
  949. roll_window_up_normal:
  950.  
  951.     mov    dx,w1.pointrow
  952.     mov    cl,w1.lastline
  953.     mov    ch,0
  954.     sub    dx,cx
  955.     dec    dx
  956.  
  957. ;now compute the number of times we need to roll.
  958.  
  959.     mov    cx,w1.pointrow
  960.     sub    cx,bx
  961.     mov    w1.pointrow,bx        ;bx is lastlimit.
  962.  
  963. ;Can we use hardware scroll?  Go if not.
  964.  
  965.   if 0
  966.     cmp    w1.firstline,0
  967.     jne    roll_window_up_3
  968.     mov    al,max_screen_line
  969.     cmp    w1.lastline,al
  970.     jne    roll_window_up_3
  971.   endif
  972.  
  973. ;Use the hardware scroll unless there isn't one.
  974.  
  975.     xchg    cx,dx            ;get the distance to skip
  976.     call    skip_to_line
  977.     mov    cx,dx
  978.  
  979. roll_window_up_4:
  980.     mov    ah,w1.firstline
  981.     mov    al,w1.lastline
  982.     call    hardware_roll_up
  983.     jc    roll_window_up_3    ;can't hardware roll.
  984.  
  985. ;now adjust window[] for the change we just made to the screen.
  986.  
  987.     mov    bl,w1.lastline
  988.     mov    bh,0
  989.     mov    al,window[bx]        ;save the current values for later.
  990.     mov    ah,inversed[bx]
  991.     push    ax
  992.     call    redraw_compare        ;remember if we're inversing here.
  993.     mov    inversed[bx],al
  994.     call    redraw_line
  995.     call    remember_redrawn
  996.     mov    window[bx],bl        ;remember that this line is real.
  997.     pop    ax            ;restore old values.
  998. roll_window_up_6:
  999.     cmp    al,TRASHED        ;has this line been trashed?
  1000.     je    roll_window_up_7
  1001.     dec    al            ;no - say the line's been moved.
  1002. roll_window_up_7:
  1003.     dec    bl
  1004.     xchg    al,window[bx]
  1005.     xchg    ah,inversed[bx]
  1006.     cmp    bl,w1.firstline
  1007.     ja    roll_window_up_6
  1008.     loop    roll_window_up_4
  1009.     jmp    short roll_window_up_2
  1010.  
  1011. ;repaint screen.
  1012.  
  1013. roll_window_up_5:
  1014.     call    center_this
  1015.     jmp    short roll_window_up_2
  1016.  
  1017. ;Use software scroll.  All we do is roll the window array.
  1018.  
  1019. roll_window_up_3:
  1020.     mov    bl,w1.lastline
  1021.     mov    bh,0
  1022.     mov    al,window[bx]        ;save the current value for later.
  1023.     mov    ah,inversed[bx]
  1024.     mov    window[bx],TRASHED
  1025. roll_window_up_1:
  1026.     dec    bl
  1027.     xchg    al,window[bx]
  1028.     xchg    ah,inversed[bx]
  1029.     cmp    bl,w1.firstline
  1030.     ja    roll_window_up_1
  1031.     loop    roll_window_up_3
  1032. roll_window_up_2:
  1033.     ret
  1034.  
  1035.  
  1036. ;enter with pointrow=current relative screen line
  1037. ;exit with a line inserted before pointrow.
  1038.     public    window_insert
  1039. window_insert:
  1040.     push    si
  1041.     mov    ax,ds            ;is this in window 1?
  1042.     cmp    ax,w1.windseg
  1043.     jne    window_insert_1
  1044.     mov    si,offset w1
  1045.     call    window_ins
  1046. window_insert_1:
  1047.     mov    ax,ds            ;is this in window 2?
  1048.     cmp    ax,w2.windseg
  1049.     jne    window_insert_2
  1050.     mov    si,offset w2
  1051.     call    window_ins
  1052. window_insert_2:
  1053.     mov    ax,ds            ;are we showing in both windows?
  1054.     cmp    ax,w1.windseg
  1055.     jne    window_insert_3
  1056.     cmp    ax,w2.windseg
  1057.     jne    window_insert_3
  1058.     call    split_at_point        ;is the split mark at or after the point?
  1059.     jnc    window_insert_3        ;no
  1060.     inc    other_row        ;yes - must increment the other row.
  1061. window_insert_3:
  1062.     pop    si
  1063.     ret
  1064.  
  1065. ;private subroutine, called by window_insert to insert a line in a window.
  1066. ;enter with si-> a window structure.
  1067. window_ins:
  1068.     mov    bx,data:[si].pointrow
  1069.     mov    al,data:[si].firstline
  1070.     cbw
  1071.     cmp    bx,ax            ;are we above the screen?
  1072.     jl    window_ins_3        ;yes - exit.
  1073.     mov    al,data:[si].lastline
  1074.     cmp    bx,ax            ;are we below the screen?
  1075.     jg    window_ins_2        ;yes - go down a row.
  1076.  
  1077.     mov    window[bx],TRASHED
  1078.     mov    al,TRASHED
  1079.     jmp    short window_ins_4
  1080. window_ins_1:
  1081.     xchg    al,window[bx]
  1082.     xchg    ah,inversed[bx]
  1083. window_ins_4:
  1084.     inc    bl
  1085.     cmp    bl,data:[si].lastline
  1086.     jbe    window_ins_1
  1087. window_ins_2:
  1088.     inc    data:[si].pointrow
  1089. window_ins_3:
  1090.     ret
  1091.  
  1092.  
  1093. ;enter with pointrow=current relative screen line
  1094. ;exit with the line at pointrow deleted.
  1095.     public    window_delete
  1096. window_delete:
  1097.     push    si
  1098.     mov    ax,ds            ;is this in window 1?
  1099.     cmp    ax,w1.windseg
  1100.     jne    window_delete_1
  1101.     mov    si,offset w1
  1102.     call    window_del
  1103. window_delete_1:
  1104.     mov    ax,ds            ;is this in window 2?
  1105.     cmp    ax,w2.windseg
  1106.     jne    window_delete_2
  1107.     mov    si,offset w2
  1108.     call    window_del
  1109. window_delete_2:
  1110.     mov    ax,ds            ;are we showing in both windows?
  1111.     cmp    ax,w1.windseg
  1112.     jne    window_delete_3
  1113.     cmp    ax,w2.windseg
  1114.     jne    window_delete_3
  1115.     call    split_at_point        ;is the split mark at or after the point?
  1116.     jnc    window_delete_3        ;no
  1117.     dec    other_row        ;yes - must decrement the other row.
  1118. window_delete_3:
  1119.     pop    si
  1120.     ret
  1121.  
  1122. ;private subroutine, called by window_delete to delete a line from a window.
  1123. ;enter with si-> a window structure.
  1124. window_del:
  1125.     mov    bx,data:[si].pointrow
  1126.     mov    al,data:[si].firstline
  1127.     cbw
  1128.     cmp    bx,ax            ;are we above the screen?
  1129.     jl    window_del_4        ;yes.
  1130.     mov    al,data:[si].lastline
  1131.     cbw
  1132.     cmp    bx,ax            ;are we below the screen?
  1133.     jg    window_del_1        ;yes.
  1134.  
  1135.     mov    window[bx],TRASHED    ;kill the line the cursor is on.
  1136.     jmp    short window_del_5    ;go into while...do loop
  1137. window_del_4:
  1138.     inc    data:[si].pointrow
  1139.     jmp    short window_del_1
  1140. window_del_3:
  1141.     mov    al,window[bx+1]
  1142.     mov    ah,inversed[bx+1]
  1143.     mov    window[bx],al
  1144.     mov    inversed[bx],ah
  1145. window_del_5:
  1146.     inc    bl
  1147.     cmp    bl,data:[si].lastline
  1148.     jb    window_del_3
  1149.     mov    window[bx],TRASHED    ;kill lastline
  1150. window_del_1:
  1151.     ret
  1152.  
  1153.  
  1154.     public    trash_line
  1155. trash_line:
  1156. ;destroy the line that the point is on if it's also in the window.
  1157.     mov    ax,ds            ;is this in window 1?
  1158.     cmp    ax,w1.windseg
  1159.     jne    trash_line_1
  1160.     mov    si,offset w1
  1161.     call    trash_line_0
  1162. trash_line_1:
  1163.     mov    ax,ds            ;is this in window 2?
  1164.     cmp    ax,w2.windseg
  1165.     jne    trash_line_2
  1166.     mov    si,offset w2
  1167.     call    trash_line_0
  1168. trash_line_2:
  1169.     ret
  1170.  
  1171.  
  1172. ;enter with si-> a window structure.
  1173. trash_line_0:
  1174.     mov    bx,data:[si].pointrow
  1175.     mov    al,data:[si].firstline
  1176.     cbw
  1177.     cmp    bx,ax
  1178.     jl    trash_line_3
  1179.     mov    al,data:[si].lastline
  1180.     cbw
  1181.     cmp    bx,ax
  1182.     jg    trash_line_3
  1183.     mov    window[bx],TRASHED
  1184. trash_line_3:
  1185.     ret
  1186.  
  1187.  
  1188.     public    up_lines
  1189. up_lines:
  1190.     mov    ax,ds            ;is this in window 2?
  1191.     cmp    ax,w1.windseg
  1192.     jne    up_lines_1
  1193.     sub    w1.pointrow,bx
  1194. up_lines_1:
  1195.     mov    ax,ds            ;is this in window 2?
  1196.     cmp    ax,w2.windseg
  1197.     jne    up_lines_2
  1198.     sub    w2.pointrow,bx
  1199. up_lines_2:
  1200.     ret
  1201.  
  1202.  
  1203.     public    down_lines
  1204. down_lines:
  1205.     mov    ax,ds            ;is this in window 1?
  1206.     cmp    ax,w1.windseg
  1207.     jne    down_lines_1
  1208.     add    w1.pointrow,bx
  1209. down_lines_1:
  1210.     mov    ax,ds            ;is this in window 2?
  1211.     cmp    ax,w2.windseg
  1212.     jne    down_lines_2
  1213.     add    w2.pointrow,bx
  1214. down_lines_2:
  1215.     ret
  1216.  
  1217.  
  1218.     public    paint_screen
  1219. paint_screen:
  1220. ;note that paint doesn't use ds.
  1221. ;what's on the screen is garbage.
  1222. ;preserve si, dx.
  1223.     mov    bl,0
  1224.     mov    al,max_screen_line
  1225.     call    trash_some_lines
  1226.     ret
  1227.  
  1228.  
  1229. center_window:
  1230. ;note that center doesn't use ds.
  1231. ;preserve dx.
  1232. center_this:
  1233.     mov    cl,w1.lastline        ;compute the middle of the screen.
  1234.     sub    cl,w1.firstline
  1235.     sar    cl,1
  1236.     add    cl,w1.firstline
  1237.     mov    ch,0
  1238.     mov    w1.pointrow,cx
  1239.     mov    bl,w1.firstline
  1240.     mov    al,w1.lastline
  1241.     call    trash_some_lines
  1242.     ret
  1243.  
  1244.  
  1245.     public    paint_window
  1246. paint_window:
  1247. ;preserve dx.
  1248.     mov    ax,textseg
  1249.     cmp    ax,w1.windseg
  1250.     jne    paint_window_1
  1251.     mov    bl,w1.firstline
  1252.     mov    al,w1.lastline
  1253.     call    trash_some_lines
  1254. paint_window_1:
  1255.     mov    ax,textseg
  1256.     cmp    ax,w2.windseg
  1257.     jne    paint_window_2
  1258.     mov    bl,w2.firstline
  1259.     mov    al,w2.lastline
  1260.     call    trash_some_lines
  1261. paint_window_2:
  1262.     ret
  1263.  
  1264.  
  1265. trash_some_lines:
  1266. ;enter with bl=first line to destroy, al=last line.
  1267. ;preserve si, dx.
  1268.     mov    w1.firstcolumn,0    ;go to the first column.
  1269.     mov    bh,0
  1270. trash_some_lines_0:
  1271.     mov    window[bx],TRASHED
  1272.     inc    bl
  1273.     cmp    bl,al
  1274.     jbe    trash_some_lines_0
  1275.     mov    al,w1.firstpossible    ;ensure that we're not above the screen.
  1276.     cbw
  1277.     cmp    w1.pointrow,ax
  1278.     jge    trash_some_lines_1    ;we're not.
  1279.     mov    w1.pointrow,ax
  1280. trash_some_lines_1:
  1281.     mov    al,w1.lastpossible    ;ensure that we're not below the screen.
  1282.     cbw
  1283.     cmp    w1.pointrow,ax
  1284.     jle    trash_some_lines_2    ;we're not.
  1285.     mov    w1.pointrow,ax
  1286. trash_some_lines_2:
  1287.     ret
  1288.  
  1289.  
  1290. ;swap the two window data structures.
  1291. swap_windows:
  1292.     mov    si,offset w1
  1293.     mov    di,offset w2
  1294.     mov    cx,(size wind_struc)
  1295. swap_windows_0:
  1296.     mov    al,data:[si]
  1297.     xchg    al,data:[di]
  1298.     mov    data:[si],al
  1299.     inc    si
  1300.     inc    di
  1301.     loop    swap_windows_0
  1302.     ret
  1303.  
  1304.  
  1305. force_point_into_window:
  1306. ;enter with al=the desired row, =0 if we don't care.
  1307. comment /**********************************************************************
  1308. * roll the window array until pointrow is on the screen.
  1309. * when we roll the array, the lines we roll in must be repainted.
  1310. * for example, assume: screen is 0..23
  1311. * if pointrow is     5, then we're done.
  1312. * if pointrow is    -7, then we must roll down 7 lines.
  1313. * if pointrow is <=-24, then we must roll down 24 lines, which says that the
  1314. *                     entire screen will be repainted.
  1315. * if pointrow is    27, then we must roll up 3 lines.
  1316. * if pointrow is  >=48, then we must roll up 24 lines, which says that the
  1317. *                  entire screen will be repainted.
  1318. *****************************************************************************/
  1319.     mov    bl,w1.firstpossible
  1320.     mov    bh,w1.lastpossible
  1321.     or    al,al            ;do we have a desired row?
  1322.     je    redisplay_1        ;no.
  1323.     dec    al
  1324.     cmp    al,bl            ;above firstpossible?
  1325.     ja    redisplay_0        ;yes - ok.
  1326.     mov    al,bl            ;no - clip to firstpossible.
  1327. redisplay_0:
  1328.     cmp    al,bh            ;below lastpossible?
  1329.     jb    redisplay_00        ;yes - ok.
  1330.     mov    al,bh            ;no - clip to lastpossible.
  1331. redisplay_00:
  1332.     mov    bl,al
  1333.     mov    bh,al
  1334. redisplay_1:
  1335.     mov    firstlastlimits,bx
  1336. ;now truncate firstlimit if we can't get there.
  1337.     mov    al,firstlimit
  1338.     cbw                ;compute the number of display lines
  1339.     sub    al,w1.firstline        ;  desired before the cursor line.
  1340.     cmp    ax,linesbefore        ;is it even possible to get there?
  1341.     jb    redisplay_2        ;yes - just do it.
  1342.     mov    ax,linesbefore        ;no - truncate firstlimit to
  1343.     add    al,w1.firstline        ;  the largest possible.
  1344.     mov    firstlimit,al
  1345. redisplay_2:
  1346.  
  1347. ;Now update row,col
  1348.  
  1349.     call    compute_cursor$
  1350.     mov    screen_column,dx
  1351.     sub    dx,w1.firstcolumn    ;are we to the left of the screen?
  1352.     jb    redisplay_01        ;yes - must roll the screen right.
  1353.     cmp    dx,word ptr num_screen_cols    ;are we on the screen?
  1354.     jb    redisplay_02        ;yes - we don't have the roll left.
  1355.  
  1356. ;roll the window to the left.
  1357.  
  1358. comment /
  1359. Eventually, we'll be smart about all this and really scroll the screen.
  1360. For now, we'll repaint the screen every time we roll.
  1361.     jmp    short redisplay_02
  1362. /
  1363.  
  1364. redisplay_01:
  1365.  
  1366. ;roll the window to the right.
  1367.  
  1368. comment /
  1369. Eventually, we'll be smart about all this and really scroll the screen.
  1370. For now, we'll repaint the screen every time we roll.
  1371. /
  1372.  
  1373.     add    dx,w1.firstcolumn    ;restore the cursor position.
  1374.     mov    bl,w1.firstline
  1375.     mov    al,w1.lastline
  1376.     call    trash_some_lines
  1377.     mov    ax,word ptr num_screen_cols
  1378.     shr    ax,1
  1379.     sub    dx,ax            ;put the cursor in middle of screen.
  1380.     jae    redisplay_03
  1381.     mov    dx,0            ;column is less than 40.
  1382. redisplay_03:
  1383.     and    dl,not 7        ;back up to previous tab stop.
  1384.     mov    w1.firstcolumn,dx    ;that is where we start redisplaying.......................
  1385. redisplay_02:
  1386.  
  1387. ;now roll the screen up or down, as needed.
  1388.  
  1389.     call    roll_window_down
  1390.     call    roll_window_up
  1391.     ret
  1392.  
  1393.  
  1394. redraw_trashed:
  1395. ;redraw all changed lines if there are any to redraw.
  1396. redraw_trashed_4:
  1397.     mov    bl,w1.firstline
  1398.     mov    bh,0
  1399.     mov    dh,0            ;initially, we don't need to redraw any.
  1400. redraw_trashed_3:
  1401.     mov    dl,window[bx]        ;get new window contents.
  1402.     or    dh,dl            ;remember if we need to redraw any.
  1403.     or    dl,dl            ;if positive, it's a line to be moved.
  1404.     js    redraw_trashed_5        ;if negative, skip it.
  1405.     cmp    dl,bl            ;is the line already there?
  1406.     je    redraw_trashed_5        ;yes - skip it.
  1407.     mov    di,offset window    ;is this row referred to?
  1408.     mov    cl,max_screen_line
  1409.     inc    cl
  1410.     mov    ch,0
  1411.     mov    al,bl
  1412.     repne    scasb            ;scan for the row.
  1413.     je    redraw_trashed_5        ;yes - we can't move something here.
  1414.     call    move_line        ;move dl to al.
  1415.     mov    dh,0            ;get the source line.
  1416.     mov    di,dx
  1417.     mov    al,inversed[di]        ;transfer the inversed contents.
  1418.     mov    inversed[bx],al
  1419.     mov    window[bx],bl        ;say that this line is where it is.
  1420.     jmp    redraw_trashed_4        ;restart search.
  1421. redraw_trashed_5:
  1422.     inc    bl
  1423.     cmp    bl,w1.lastline
  1424.     jbe    redraw_trashed_3
  1425.  
  1426.     cmp    inverse_flag,0        ;if we're inversing, we might need to redraw.
  1427.     jne    redraw_trashed_1
  1428.     or    dh,dh            ;do we need to redraw any lines?
  1429.     jns    redraw_trashed_9        ;no.
  1430.  
  1431. redraw_trashed_1:
  1432.     mov    bl,w1.firstline
  1433.     mov    bh,0
  1434.     mov    cx,this_row        ;get the row that the point is on.
  1435.     sub    cx,bx
  1436.     call    skip_to_line        ;find the first line on the screen.
  1437.     call    redraw_anyway        ;see if we need to redraw anyway.
  1438. redraw_trashed_7:
  1439.     call    redraw_compare        ;remember if we're inversing here.
  1440.     mov    inversed[bx],al
  1441.     cmp    window[bx],0
  1442.     jns    redraw_trashed_a        ;if negative, redraw it.
  1443.     call    redraw_line
  1444.     mov    window[bx],bl        ;remember that this line is drawn.
  1445. redraw_trashed_a:
  1446.     call    remember_redrawn
  1447.     inc    bl
  1448.     cmp    bl,w1.lastline
  1449.     jbe    redraw_trashed_7
  1450. redraw_trashed_9:
  1451.     mov    inversing,0        ;say that we're not inversing.
  1452.     ret
  1453.  
  1454.  
  1455. remember_redrawn:
  1456. ;enter with si->text, bx=screen line.
  1457. ;exit with si->next line.
  1458.     call    nextline
  1459.     shl    inversed[bx],1
  1460.     shl    inversed[bx],1
  1461.     call    redraw_compare
  1462.     or    inversed[bx],al
  1463.     ret
  1464.  
  1465.  
  1466. redraw_anyway:
  1467. ;preserve si,bx.
  1468.     cmp    inverse_flag,0
  1469.     je    redraw_anyway_1
  1470.     push    si
  1471.     push    bx
  1472. redraw_anyway_2:
  1473.     call    redraw_compare
  1474.     push    ax
  1475.     call    nextline        ;see if this line contains the mark or point.
  1476.     call    redraw_compare
  1477.     pop    cx
  1478.     mov    ch,cl            ;save a copy.
  1479.     xor    cl,al            ;see if the bits changed.
  1480.     test    cl,1            ;is the point in this line?
  1481.     jne    redraw_anyway_yes    ;yes - must redraw.
  1482.     shl    ch,1
  1483.     shl    ch,1
  1484.     or    al,ch            ;make up the compare byte.
  1485.     cmp    al,inversed[bx]        ;have they changed?
  1486.     je    redraw_anyway_no    ;no - don't necessarily redraw.
  1487. redraw_anyway_yes:
  1488.     mov    window[bx],TRASHED    ;say that this line is gone.
  1489. redraw_anyway_no:
  1490.     inc    bl
  1491.     cmp    bl,w1.lastline
  1492.     jbe    redraw_anyway_2
  1493.     pop    bx
  1494.     pop    si
  1495. redraw_anyway_1:
  1496.     ret
  1497.  
  1498.  
  1499. redraw_compare:
  1500. ;enter with si->text buffer.
  1501. ;exit with al and 1 = 1 if si<point,
  1502. ;          al and 2 = 2 if si<mark.
  1503.     cmp    si,inverse_mark        ;set cy if si is below inverse_mark (mark)
  1504.     rcl    al,1
  1505.     cmp    si,bottop        ;set cy if si is below bottop (point)
  1506.     rcl    al,1
  1507.     and    al,3            ;get rid of other bits.
  1508.     ret
  1509.  
  1510.  
  1511.  
  1512. skip_to_line:
  1513. ;enter with cx=number of lines to move forward or backward.
  1514. ;Note: positive values move toward top of file.
  1515. ;return si -> beginning of desired line.
  1516. ;don't destroy dx.
  1517.     mov    si,this_point        ;get the point.
  1518.     or    cx,cx            ;is cx negative?
  1519.     js    skip_to_line_4        ;yes - we have to move forward.
  1520.     cmp    [si-2].w,LINENEW    ;if we're not at the beginning of
  1521.     je    skip_to_line_3        ;  this line, backup to beginning.
  1522.     call    prevline
  1523. skip_to_line_3:
  1524.     jcxz    skip_to_line_2
  1525. skip_to_line_1:
  1526.     call    prevline
  1527.     loopne    skip_to_line_1
  1528.     jne    skip_to_line_2        ;did we hit the beginning?
  1529.     inc    cx            ;yes - restore the count.
  1530.     sub    this_row,cx        ;adjust this row.
  1531.     jmp    short skip_to_line_2
  1532. skip_to_line_4:
  1533.     neg    cx            ;make cx into a positive count.
  1534.                     ;cx is at least one.
  1535. skip_to_line_5:
  1536.     call    nextline
  1537.     loopne    skip_to_line_5
  1538. skip_to_line_2:
  1539.     mov    al,inverse_flag        ;are we inversing?
  1540.     cmp    al,0
  1541.     je    skip_to_line_6        ;no.
  1542.     push    bx
  1543.     push    dx
  1544.     push    si
  1545.     call    get_mark        ;the mark is in inverse_flag
  1546.     mov    inverse_mark,si        ;remember where the inverse mark is.
  1547.     pop    si
  1548.     pop    dx
  1549.     pop    bx
  1550. skip_to_line_6:
  1551.     ret
  1552.  
  1553.  
  1554. redraw_line:
  1555. ;enter with si -> line to be redrawn, bl=row of line.
  1556. ;paint from firstcolumn for num_screen_cols columns.
  1557. ;this routine is intense.
  1558. ;preserve cx, bx
  1559.     call    redraw_set
  1560.     mov    di,0            ;start at column zero.
  1561.     mov    dh,0
  1562.     mov    dl,bl
  1563.     mov    bl,-1            ;start without trailing blanks.
  1564.     cmp    si,botbot        ;are we at bottom already?
  1565.     je    redraw_line_9_j_1    ;yes - clear to eol.
  1566. redraw_line_2:
  1567.     call    redraw_pointer
  1568.     cmp    si,botbot        ;are we at bottom already?
  1569.     je    redraw_line_3        ;yes - exit.
  1570.     mov    ax,[si]
  1571.     cmp    ax,LINENEW        ;done with line?
  1572.     je    redraw_line_3        ;yes - exit.
  1573.     inc    si
  1574.     cmp    dh,num_screen_cols    ;at right hand column?
  1575.     jae    redraw_line_d        ;yes - don't print.
  1576.     cmp    di,w1.firstcolumn    ;before first column?
  1577.     jb    redraw_line_4        ;yes - just compute new column.
  1578.     cmp    al,' '            ;possible trailing blanks.
  1579.     je    redraw_line_a
  1580.     cmp    al,HT
  1581.     jne    redraw_line_b        ;not trailing blanks - forget.
  1582. redraw_line_a:
  1583.     cmp    bl,-1            ;are we already remembering?
  1584.     jne    redraw_line_c        ;yes - don't remember again.
  1585.     mov    bl,dh            ;found a trailing blank character,
  1586.     mov    bp,si            ;  remember where it was.
  1587.     jmp    short redraw_line_c
  1588. redraw_line_b:
  1589.     mov    bl,-1            ;printable char - forget trailing blanks.
  1590. redraw_line_c:
  1591.     call    xy_char_put
  1592.     jmp    redraw_line_2
  1593. redraw_line_d:
  1594.     cmp    dh,num_screen_cols    ;did we just get there?
  1595.     ja    redraw_line_2        ;no.
  1596.     dec    dh
  1597.     mov    ax,8*256+MORE_CHAR    ;yes - print the "more" symbol.
  1598.     call    xychrout
  1599.     mov    dh,num_screen_cols    ;say that we're in the next column.
  1600.     inc    dh
  1601.     jmp    redraw_line_2
  1602. redraw_line_4:
  1603.     inc    di
  1604.     cmp    al,HT            ;only tabs are special
  1605.     jne    redraw_line_2
  1606.     mov    ax,di
  1607.     add    ax,tab_size        ;round up to next tab stop.
  1608.     or    ax,tab_size        ;same as 'and not'.
  1609.     xor    ax,tab_size
  1610.     mov    di,ax
  1611.     jmp    redraw_line_2
  1612. redraw_line_9_j_1:
  1613.     jmp    redraw_line_9
  1614. redraw_line_3:
  1615.     cmp    showblanks,0        ;should we show blanks?
  1616.     je    redraw_line_8
  1617.     cmp    bl,-1            ;are there any trailing blanks?
  1618.     je    redraw_line_8        ;no.
  1619.     mov    dh,bl            ;restore the column.
  1620.     xchg    si,bp            ;save the current and restore the old.
  1621.     dec    si
  1622.     call    redraw_set
  1623. redraw_line_7:
  1624.     call    redraw_pointer
  1625.     cmp    si,botbot        ;hit the bottom yet?
  1626.     je    redraw_line_e        ;yes - we're done.
  1627.     mov    ax,[si]            ;get the next char.
  1628.     cmp    ax,LINENEW
  1629.     je    redraw_line_e
  1630.     cmp    dh,num_screen_cols
  1631.     jae    redraw_line_f
  1632.     inc    si
  1633.     cmp    al,' '            ;it can only be a tab or a space.
  1634.     je    redraw_line_6        ;must be a space.
  1635. redraw_line_5:
  1636.     cmp    dh,num_screen_cols
  1637.     jae    redraw_line_f
  1638.     mov    ax,8*256+TRAIL_TAB    ;output a trailing tab char.
  1639.     call    xychrout
  1640.     inc    dh
  1641.     test    dh,byte ptr tab_size    ;at a tab stop yet?
  1642.     jne    redraw_line_5        ;no.
  1643.     jmp    redraw_line_7
  1644. redraw_line_6:                ;output a trailing blank char.
  1645.     mov    ax,8*256+TRAIL_BLANK
  1646.     call    xychrout
  1647.     inc    dh
  1648.     jmp    redraw_line_7
  1649. redraw_line_f:
  1650.     dec    dh
  1651.     mov    ax,8*256+MORE_CHAR    ;yes - print the "more" symbol.
  1652.     call    xychrout
  1653.     inc    dh
  1654. redraw_line_e:
  1655.     mov    si,bp            ;restore the text pointer.
  1656. redraw_line_8:
  1657.     cmp    dh,num_screen_cols    ;put a newline symbol if there's room.
  1658.     jae    redraw_line_9
  1659.     cmp    inversing,0        ;only if we're inversing.
  1660.     je    redraw_line_9
  1661.     mov    ax,8*256+NEWLINE_CHAR    ;newline symbol.
  1662.     call    xychrout
  1663.     inc    dh
  1664. redraw_line_9:
  1665.     call    clear_to_eol
  1666.     mov    bh,0            ;restore bx.
  1667.     mov    bl,dl
  1668.     ret
  1669.  
  1670.  
  1671. redraw_pointer:
  1672. ;adjust si from the top to the bottom if necessary, and adjust inversing.
  1673.     cmp    si,topbot        ;at the point yet?
  1674.     jne    redraw_pointer_1    ;no.
  1675.     mov    si,bottop
  1676.     cmp    inverse_flag,0        ;are we inversing?
  1677.     je    redraw_pointer_1    ;no.
  1678.     mov    ax,ds
  1679.     cmp    ax,inverse_seg        ;is this our segment?
  1680.     jne    redraw_pointer_1    ;no.
  1681.     not    inversing        ;say that we've passed the point.
  1682. redraw_pointer_1:
  1683.     cmp    si,inverse_mark        ;are we at the inverse mark?
  1684.     jne    redraw_pointer_2    ;yes - maybe inverse.
  1685.     cmp    inverse_flag,0        ;are we inversing?
  1686.     je    redraw_pointer_2    ;no.
  1687.     mov    ax,ds
  1688.     cmp    ax,inverse_seg        ;is this our segment?
  1689.     jne    redraw_pointer_2    ;no.
  1690.     not    inversing        ;say that we've passed the point.
  1691. redraw_pointer_2:
  1692.     ret
  1693.  
  1694.  
  1695. redraw_set:
  1696.     cmp    si,topbot        ;have we hit the top bottm yet?
  1697.     jne    redraw_set_3
  1698.     mov    si,bottop
  1699. redraw_set_3:
  1700.     cmp    inverse_flag,0        ;if we're not inversing, don't inverse.
  1701.     je    redraw_set_1
  1702.     mov    ax,ds
  1703.     cmp    ax,inverse_seg        ;is this our segment?
  1704.     jne    redraw_set_1        ;no.
  1705.     call    redraw_compare
  1706.     cmp    si,inverse_mark        ;are we exactly at the mark?
  1707.     jne    redraw_set_2        ;no - just check parity.
  1708.     xor    al,2            ;yes - flip the associated bit.
  1709. redraw_set_2:
  1710.     mov    inversing,0        ;say that we're not inversing.
  1711.     or    al,al            ;look for 00,11 or 10,01
  1712.     jpe    redraw_set_1        ;go if not within point and mark.
  1713.     not    inversing        ;say that we're inversing.
  1714. redraw_set_1:
  1715.     ret
  1716.  
  1717.  
  1718. xy_char_put:
  1719. ;put a char on the screen.  Interpret tabs.
  1720.     cmp    al,HT
  1721.     jne    xy_char_put_1
  1722. xy_char_put_2:
  1723.     mov    ax,8*256+TAB_BLANK    ;output a tab blank char.
  1724.     call    xychrout
  1725.     inc    dh
  1726.     test    dh,byte ptr tab_size
  1727.     jnz    xy_char_put_2
  1728.     ret
  1729. xy_char_put_1:
  1730.     mov    ah,0
  1731.     call    xychrout
  1732.     inc    dh
  1733. xy_char_put_4:
  1734.     ret
  1735.  
  1736.  
  1737.     public    prevline
  1738. prevline:
  1739. ;retreat si to the previous line.
  1740. ;return zr if si->beginning of file (and leave si alone)
  1741. ;return nz otherwise.
  1742.  
  1743. ;are we at the beginning of the file already?
  1744.     cmp    si,toptop
  1745.     je    prevline_beginning    ;yes - exit.
  1746.  
  1747. ;where are we in the file?
  1748.     cmp    si,topbot        ;at, before or after the point?
  1749.     jbe    prevline_before
  1750. prevline_after:
  1751.     dec    si
  1752.     cmp    si,bottop        ;have we reached the top of the bottom?
  1753.     je    prevline_at        ;yes - drop down to prevline_before.
  1754.     cmp    [si-2].w,LINENEW    ;at the beginning of a new line?
  1755.     jne    prevline_after        ;no - keep looking.
  1756.     dec    si            ;did we just find a non-real newline?
  1757.     cmp    si,bottop        ;if we did, then si is now at bottop
  1758.     je    prevline_at        ;  and we need to keep searching.
  1759.     inc    si            ;restore si and exit.
  1760.     jmp    short prevline_exit
  1761.  
  1762. prevline_at:
  1763.     mov    si,topbot        ;start searching at the bottom
  1764.     inc    si            ;  of the top.
  1765. prevline_before:
  1766.     dec    si
  1767.     cmp    [si-2].w,LINENEW    ;at the beginning of a new line?
  1768.     jne    prevline_before        ;no - keep looking.
  1769. prevline_exit:
  1770.     or    si,si            ;return nz
  1771. prevline_beginning:
  1772.     ret
  1773.  
  1774.  
  1775.     public    nextline
  1776. nextline:
  1777. ;advance si to the next line.
  1778. ;return zr if si->end of file (and leave si alone)
  1779. ;return nz otherwise.
  1780.     cmp    si,topbot
  1781.     jne    nextline_1
  1782.     mov    si,bottop
  1783. nextline_1:
  1784.     cmp    si,botbot
  1785.     je    nextline_2
  1786.     cmp    [si].w,LINENEW
  1787.     je    nextline_3
  1788.     inc    si
  1789.     jmp    nextline
  1790. nextline_3:
  1791.     add    si,2
  1792.     or    si,si
  1793.     ret
  1794. nextline_2:
  1795.     push    ax
  1796.     xor    ax,ax
  1797.     pop    ax
  1798.     ret
  1799.  
  1800.  
  1801.     public    compute_one
  1802. compute_one:
  1803.     cmp    al,HT
  1804.     jne    compute_one_1
  1805.     or    dl,byte ptr tab_size    ;same as 'and not'
  1806.     xor    dl,byte ptr tab_size
  1807.     add    dx,tab_size
  1808. compute_one_1:
  1809.     inc    dx
  1810.     ret
  1811.  
  1812.  
  1813. code    ends
  1814.  
  1815.     end
  1816.